Skip to content

Conversation

@akulakum
Copy link
Contributor

@akulakum akulakum commented Nov 14, 2025

COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7323

Vidcast Link: https://app.vidcast.io/share/7babff72-18e8-459a-bf67-2727b3256273

This pull request addresses

The need to support automatic task acceptance for contact center agents in specific scenarios, improving agent efficiency and user experience. Currently, agents must manually accept all incoming tasks, which creates unnecessary delays in certain workflows such as:

  • WebRTC calls with auto-answer enabled in the agent profile.
  • Agent-initiated outbound calls (WebRTC and digital channels)

Additionally, this PR adds support for the AGENT_OFFER_CAMPAIGN_RESERVATION event, which was missing from the SDK's event handling syst

by making the following changes

  1. Auto-Answer Infrastructure
    Added helper functions in TaskUtils.ts to determine auto-answer eligibility:
    isAutoAnswerEnabled() - Checks if auto-answer is enabled in agent profile
    isWebRTCCall() - Validates WebRTC telephony calls
    isDigitalOutbound() - Identifies digital outbound interactions (Email/SMS)
    isAgentInitiatedOutdial() - Verifies agent-initiated outdial scenarios
    shouldAutoAnswerTask() - Main orchestrator that evaluates all auto-answer conditions

  2. TaskManager Integration
    Added handleAutoAnswer() private method that automatically accepts tasks when conditions are met
    Integrated auto-answer logic into three event handlers:
    AGENT_OFFER_CONTACT - Standard contact offers
    AGENT_OFFER_CONSULT - Consultation offers
    AGENT_OFFER_CAMPAIGN_RESERVATION - Campaign reservation offers (new)

  3. Campaign Reservation Support
    Added AGENT_OFFER_CAMPAIGN_RESERVATION to CC_TASK_EVENTS for automatic task lookup
    Created new SDK event: TASK_EVENTS.TASK_OFFER_CAMPAIGN_RESERVATION
    Implemented event handler in TaskManager.ts following the same pattern as other offer events
    Added event listener in sample app (app.js)

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

< ENUMERATE TESTS PERFORMED, WHETHER MANUAL OR AUTOMATED >

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

I certified that

  • I have read and followed contributing guidelines
  • I discussed changes with code owners prior to submitting this pull request
  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the documentation accordingly

Make sure to have followed the contributing guidelines before submitting.

@akulakum akulakum requested a review from a team as a code owner November 14, 2025 13:38
@akulakum akulakum added the validated If the pull request is validated for automation. label Nov 14, 2025
@aws-amplify-us-east-2
Copy link

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-4571.d3m3l2kee0btzx.amplifyapp.com


try {
await task.accept();
LoggerProxy.info(`Task auto-answered successfully`, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add metrics for this - it would be good to know if the task was auto answer or not.
We can re-use the accept metrics itself but add another field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

} catch (error) {
// Reset isAutoAnswering flag on failure
task.updateTaskData({...task.data, isAutoAnswering: false});
LoggerProxy.error(`Failed to auto-answer task`, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here.. have metrics for error for auto answer also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

*/
private async handleAutoAnswer(task: ITask): Promise<void> {
if (!task || !task.data || !task.data.isAutoAnswering) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of returning, we throw an error here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept as return — this guard clause handles the normal operation where most tasks don’t have auto-answer enabled. Throwing an error here would treat the expected path as exceptional and introduce unnecessary error handling in the callers.

* @param interaction - The interaction object
* @returns true if this is a digital outbound, false otherwise
*/
export const isDigitalOutbound = (interaction: Interaction): boolean => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand we might need this in the future but just curious are we using it now also?
Just an ask.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, we are not using this logic. It’s included for future use.

This implementation has been taken from the Agent Desktop and will be applicable for Desktop, Outdial, and Digital Outbound scenarios.

* @param agentId - Current agent ID
* @returns true if agent initiated the outdial, false otherwise
*/
export const isAgentInitiatedOutdial = (interaction: Interaction, agentId: string): boolean => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
export const isAgentInitiatedOutdial = (interaction: Interaction, agentId: string): boolean => {
export const hasAgentInitiatedOutdial = (interaction: Interaction, agentId: string): boolean => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

@akulakum akulakum requested a review from adhmenon November 24, 2025 09:18
Copy link
Contributor

@adhmenon adhmenon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@adhmenon adhmenon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making thw quick changes.

@akulakum akulakum merged commit a5a12ba into webex:next Nov 25, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

validated If the pull request is validated for automation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants